<template>
  <div class="bj-upload-file">
    <a-upload
      class="bj-upload-button"
      :file-list="fileList"
      :accept="getFileAccent"
      :beforeUpload="
        (file) => {
          return beforeUpload(file);
        }
      "
    >
      <a-button
        type="primary"
        style="margin-left: 0"
        v-if="!viewMode"
        :disabled="value.length >= count"
      >
        点击上传
      </a-button>
    </a-upload>
    <!-- 附件 -->
    <div class="choosed-file-warp" v-if="value.length > 0 && type == 'file'">
      <div
        class="file-list flex"
        :class="item.fail && 'fail'"
        v-for="(item, index) in value"
        :key="index"
      >
        <div class="base-info flex">
          <!-- 图标 -->
          <div class="icon">
            <a-icon
              v-if="item.fail && !item.loading"
              type="info-circle"
              :style="{ fontSize: '20px', color: '#ff6565' }"
            />
            <a-icon type="loading" v-else-if="item.loading" />
            <img
              v-else
              :src="filterIcon(item[replaceFields.fileType])"
              alt=""
              srcset=""
            />
          </div>
          <!-- 文件名 -->
          <div
            class="name"
            :title="item[replaceFields.fileName]"
            @click="viewFile(item)"
          >
            {{ item[replaceFields.fileName] }}
          </div>
          <!-- 文件大小 -->
          <div class="size">
            {{ (item[replaceFields.fileSize] / 1024).toFixed(2) }}kb
          </div>
          <!-- 删除 -->
          <div
            class="delete-button"
            v-if="!viewMode"
            @click="deleteImg(item, index)"
          >
            <a-icon
              type="close"
              :style="{
                fontSize: '12px',
                color: '#FF3F4A',
              }"
            />
          </div>
          <!-- 下载 -->
          <div
            class="delete-button download-button"
            v-if="viewMode"
            @click="download(item)"
          >
            <a-icon
              type="download"
              :style="{
                fontSize: '16px',
                color: '#FF3F4A',
              }"
            />
          </div>
        </div>
      </div>
    </div>
    <!-- 视频 -->
    <div
      class="choosed-videos-warp flex"
      v-if="value.length > 0 && type == 'video'"
    >
      <div class="file-list" v-for="(item, index) in value" :key="index">
        <video :src="item[replaceFields.videoSrc]" controls />
        <!-- 删除按钮 -->
        <div
          class="delete-button"
          @click="deleteImg(item, index)"
          v-if="!item.loading && !viewMode"
        >
          <a-icon
            type="close"
            :style="{
              fontSize: '12px',
              color: '#ffffff',
            }"
          />
        </div>
        <!-- 上传loading -->
        <div class="up-loading" v-if="item.loading && !viewMode">
          <a-icon type="loading" :style="{ fontSize: '30px', color: '#333' }" />
        </div>
        <!-- 上传失败图标 -->
        <div
          class="up-loading up-error"
          v-if="item.fail && !item.loading && !viewMode"
        >
          <a-icon
            type="info-circle"
            :style="{ fontSize: '30px', color: '#ff6565' }"
          />
          <div>上传失败</div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  model: {
    prop: "value",
    event: "input",
  },
  props: {
    type: {
      type: String,
      default: "file",
    },
    value: {
      type: Array,
      default: () => {
        return [];
      },
    },
    viewMode: {
      type: Boolean,
      default: false,
    },
    //最大上传数量
    count: {
      type: Number,
      default: 0,
    },
    //
    replaceFields: {
      type: Object,
      default: () => {
        return {
          fileName: "fileName",
          fileSize: "fileSize",
          fileType: "fileType",
          videoSrc: "src",
        };
      },
    },
  },
  data() {
    return {
      fileList: [],
      //附件
      fileAccept:
        ".txt,.pdf,.doc,.docx,.xls,.xlsx,.xml,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,.png,.jpg,.jpeg,.bmp,.gif",
      //视频
      videoAccept: "video/*",
    };
  },
  computed: {
    getFileAccent() {
      let { type, fileAccept, videoAccept } = this;
      switch (type) {
        case "file":
          return fileAccept;

        case "video":
          return videoAccept;

        default:
          return fileAccept;
      }
    },
  },
  mounted() {},
  methods: {
    //下载
    download(item) {
      this.$emit("download", item);
    },

    //附件预览
    viewFile(item) {
      if (this.viewMode) {
        this.$emit("preview", item);
      }
    },

    //监听文件选择
    beforeUpload(file) {
      let { name = "", size = 0 } = file;
      let { value, replaceFields, type } = this;
      let lastIdx = name.lastIndexOf(".");
      let fileType = "." + name.substring(lastIdx + 1);
      let itemFileData = {
        file,
        $$DataType: 1,
        [replaceFields.fileType]: fileType,
        [replaceFields.fileName]: name,
        [replaceFields.fileSize]: size,
      };
      if (type == "video") {
        this.parseVideo(file).then((res) => {
          itemFileData[replaceFields.videoSrc] = res;
          this.$emit("input", [...value, itemFileData]);
          setTimeout((_) => {
            this.$emit("change", {
              ...itemFileData,
              index: this.value.length - 1,
            });
          });
        });
        return Promise.reject();
      } else {
        this.$emit("input", [...value, itemFileData]);
        setTimeout((_) => {
          this.$emit("change", {
            ...itemFileData,
            index: this.value.length - 1,
          });
        });
        return false;
      }
    },

    //解析视频流
    parseVideo(file) {
      return new Promise((resolve, reject) => {
        let filereader = new FileReader();
        filereader.onload = (e) => {
          let src = e.target.result;
          resolve(src);
        };
        filereader.readAsDataURL(file);
      });
    },

    //删除
    deleteImg(file, index) {
      let { value } = this;
      let data = value.filter((v, i) => i != index);
      this.$emit("input", data);
      this.$emit("remove", { file, index });
    },

    //文件icon
    filterIcon(type = "") {
      if (type) type = type.toLowerCase();
      switch (type) {
        case ".pdf":
          return "https://jszhgd.cn/static/app/pdf.png";
        case ".doc":
        case ".docx":
          return "https://jszhgd.cn/static/app/doc.png";
        case ".xls":
        case ".xlsx":
          return "https://jszhgd.cn/static/app/xls.png";
        case ".ppt":
        case ".pptx":
        case ".pps":
          return "https://jszhgd.cn/static/app/ppt.png";
        case ".png":
        case ".jpg":
        case ".jpeg":
        case ".bmp":
        case ".gif":
          return "https://jszhgd.cn/static/app/image.png";
        default:
          return "https://jszhgd.cn/static/app/other.png";
      }
    },
  },
};
</script>
<style lang="less" scoped>
.bj-upload-file {
  .flex();
  flex-direction: column;
  .choosed-file-warp {
    width: 476px;
    height: 156px;
    background: #ffffff;
    border: 1px solid #dcdee2;
    border-radius: 4px;
    margin: 4px 0 0 4px;
    padding: 6px 0 0 0;
    .custom-scrollbar();
    .file-list {
      flex-direction: column;
      padding: 0 0 12px 16px;
      .base-info {
        align-items: center;
        height: 25px;
        position: relative;
        .icon {
          width: 22px;
          height: 22px;
          margin-right: 6px;
          .flex();
          align-items: center;
          justify-content: center;
          flex-shrink: 0;
          overflow: hidden;
          img {
            width: 20px;
            height: 20px;
          }
        }
        .name {
          cursor: pointer;
          color: #525a5d;
          overflow: hidden; //溢出隐藏
          white-space: nowrap; // 强制一行显示
          text-overflow: ellipsis;
          &:hover {
            color: var(--primary-color);
            text-decoration: underline;
          }
          flex: 1;
        }
        .size {
          flex-shrink: 0;
          margin-left: 20px;
          margin-right: 36px;
        }
        .delete-button {
          width: 16px;
          height: 16px;
          cursor: pointer;
          position: absolute;
          background: rgba(255, 63, 74, 0.1);
          border-radius: 50%;
          flex-shrink: 0;
          .flex();
          align-items: center;
          justify-content: center;
          top: 6px;
          right: 10px;
          .anticon {
            transform: scale(0.8);
          }
          &.download-button {
            background: none;
            border-radius: 0;
            .anticon {
              color: var(--primary-color) !important;
              transform: scale(1);
            }
          }
        }
      }
      &.fail {
        .base-info {
          .name {
            color: red;
          }
          .size {
            color: red;
          }
        }
      }
      .progress-bar {
        height: 4px;
        background: #f1f1f3;
        border-radius: 2px;
        margin: -4px 20px 0 22px;
      }
    }
  }
  .choosed-videos-warp {
    flex-wrap: wrap;
    .file-list {
      width: 168px;
      height: 162px;
      background: #f5f7fa;
      margin: 0 20px 20px 0;
      position: relative;
      .up-loading {
        position: absolute;
        width: 100%;
        height: 100%;
        .flex();
        align-items: center;
        justify-content: center;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        background: rgba(255, 255, 255, 0.5);
        &.up-error {
          background: rgba(0, 0, 0, 0.3);
          flex-direction: column;
          color: #ff6565;
          font-weight: bold;
        }
      }
      video {
        width: 100%;
        height: 100%;
        background: #333;
      }
      .delete-button {
        position: absolute;
        width: 20px;
        height: 20px;
        background: #ff6565;
        top: -10px;
        right: -10px;
        border-radius: 50%;
        cursor: pointer;
        .flex();
        align-items: center;
        justify-content: center;
        z-index: 99;
      }
    }
  }
}
</style>
